#pragma once
#include "dxroids.h"

#include <memory>
#include <vector>

#include "CharacterRenderer.h"
#include "EnemyShip.h"
#include "Explosion.h"
#include "Player.h"
#include "PlayerShip.h"
#include "SoundManager.h"
#include "SpaceRock.h"

namespace dxroids
{
   class Application
   {
   public:
      Application();      

      HRESULT Initialize();
      void RunMessageLoop();

   private:

      enum GameState
      {
         None,
         WaitingToStart,
         PlayingLevel,
         SwitchingLevel,
         Paused
      };

      HRESULT CreateDeviceIndependentResources();
      HRESULT CreateDeviceResources();      
      HRESULT OnRender();

      void UpdateFrame(GameTime const & _timer);
      void CheckCollisions();

      // keyboard input
      void OnKeyDown(WPARAM _param);
      void OnKeyUp(WPARAM _param);

      void DiscardDeviceResources();
      void OnResize(UINT _width, UINT _height);
      void HandleGamepadInput(XINPUT_GAMEPAD const & _gamepad_input);
      void DestroyShip(Ship & _ship);

      void AddRocks(
         std::pair<std::unique_ptr<SpaceRock>, std::unique_ptr<SpaceRock>> & _new_rocks,
         std::vector<std::unique_ptr<dxroids::SpaceRock>> & _list);

      void CheckCollision(dxroids::Ship & _ship, dxroids::SpaceRock & _rock,
         std::vector<std::unique_ptr<dxroids::SpaceRock>> & _new_rocks);

      static LRESULT CALLBACK MessageHandler(
         HWND _window_handle,
         UINT _message, 
         WPARAM _w_param, 
         LPARAM _l_param);

      void PlaySoundEffect(SoundEffect _effect, bool _loop);
      void StopSoundEffect(SoundEffect _effect);

      std::unique_ptr<SpaceRock> NewRock();
      std::unique_ptr<EnemyShip> LaunchEnemyShip(EnemyShip::Size _size);

      int32_t LoadHighScore();

   private:

      std::unique_ptr<TCHAR []> title_bar_text_;
      std::unique_ptr<TCHAR []> main_windows_class_name_;
            
      DXROIDS_COM_PTR<ID2D1SolidColorBrush> primary_brush_;
      DXROIDS_COM_PTR<ID2D1SolidColorBrush> secondary_brush_;
      DXROIDS_COM_PTR<ID2D1SolidColorBrush> debug_brush_;
      DXROIDS_COM_PTR<ID2D1HwndRenderTarget> render_target_;        

      HWND window_handle_;
      int32_t gamepad_user_index_;
      int64_t frame_counter_;

      int32_t next_thump_;
      int32_t thump_interval_;
      
      CharacterRenderer char_renderer_;      

      std::unique_ptr<EnemyShip> enemy_ship_;
      std::unique_ptr<PlayerShip> player_ship_;
      std::vector<std::unique_ptr<SpaceRock>> rocks_;
      std::vector<std::unique_ptr<PlayerShip>> remaining_ships_;

      std::shared_ptr<SoundManager> sound_manager_;
      std::vector<std::unique_ptr<GameObject>> explosions_;
      Player player_;      
      int32_t high_score_;

      struct GameStateTracker
      {
         GameStateTracker() : Current(GameState::WaitingToStart), Previous(GameState::None) { }
         void Set(GameState _state)
         {
            Previous = Current;
            Current = _state;
         }
         void Revert()
         {
            DxRoidsAssert(Previous != GameState::None);
            Current = Previous;
            Previous = None;
         }
         GameState Current;
         GameState Previous;
      };

      GameStateTracker game_state_;

   };
}

